package com.mes.schedule.manager;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mes.basicdata.domain.Part;
import com.mes.common.util.IdentityGenerator;
import com.mes.schedule.algorithm.TaskSFCalc;
import com.mes.schedule.domain.SOperationTask;
import com.mes.schedule.domain.SPartTask;
import com.mes.schedule.manager.iface.ILotAdvisor;
import com.mes.task.domain.Demand;

public class LotAdvisor implements ILotAdvisor{
	TaskSFCalc taskSFCalc = new TaskSFCalc();

	public class TaskItemLocation {
		int totalLocation;
		SPartTask partTask;
		int localLocation;
		SPartTask splitTask;
		Demand demand;
	}

	// 整体把数量打散，<int,sparttask,int>
	public static void main(String[] args) {

		List<Demand> demandList = new ArrayList<Demand>();
		for (int i = 0; i < 3; i++) {
			Demand demand = new Demand();
			demand.setNotes("第" + i + "个需求");
			demand.setUuid(IdentityGenerator.GetIdentityString());
			demandList.add(demand);
		}

		Calendar calendar = Calendar.getInstance();
		calendar.set(2014, 1, 20, 0, 0);
		calendar.getTime();
		Date lateFinish = calendar.getTime();
		demandList.get(0).setLateFinish(lateFinish);
//		demandList.get(0).setPlanQty(10.0);

		Calendar calendar2 = Calendar.getInstance();
		calendar2.set(2014, 2, 1, 0, 0);
		calendar2.getTime();
		Date lateFinish2 = calendar2.getTime();
		demandList.get(1).setLateFinish(lateFinish2);
//		demandList.get(1).setPlanQty(20.0);

		Calendar calendar3 = Calendar.getInstance();
		calendar3.set(2014, 2, 10, 0, 0);
		calendar3.getTime();
		Date lateFinish3 = calendar3.getTime();
		demandList.get(2).setLateFinish(lateFinish3);
//		demandList.get(2).setPlanQty(30.0);

		List<SPartTask> partTaskList = new ArrayList<SPartTask>();
		for (int i = 0; i < 3; i++) {
			SPartTask partTask = new SPartTask();
			partTask.setNotes("第" + i + "个主任务");
			partTask.setUuid(IdentityGenerator.GetIdentityString());
			partTask.setTaskUid(IdentityGenerator.GetIdentityString());
			List<SOperationTask> opList = new ArrayList<SOperationTask>();
			for (int j = 0; j < 20; j++) {
				SOperationTask opTask = new SOperationTask();
				opTask.setTaskUid(IdentityGenerator.GetIdentityString());
				opTask.setUuid(IdentityGenerator.GetIdentityString());
				opTask.setEstiPreTime(60.0);
				opTask.setEstiRunTime(30.0);
				opTask.setOperationId((float) j);
				opList.add(opTask);
			}
			partTask.setOperationTaskList(opList);
			partTaskList.add(partTask);
		}

		SPartTask partTask1 = partTaskList.get(0);
		partTask1.setPlanQty(30.0);
		partTask1.getOperationTaskList().remove(0);
		partTask1.getOperationTaskList().remove(1);
		partTask1.getOperationTaskList().remove(2);
		partTask1.getOperationTaskList().remove(3);
		partTask1.getOperationTaskList().remove(4);
		for (SOperationTask opTask : partTask1.getOperationTaskList()) {
			opTask.setPlanQty(partTask1.getPlanQty());
		}

		SPartTask partTask2 = partTaskList.get(1);
		partTask2.setPlanQty(20.0);
		for (SOperationTask opTask : partTask2.getOperationTaskList()) {
			opTask.setPlanQty(partTask2.getPlanQty());
		}

		SPartTask partTask3 = partTaskList.get(2);
		partTask3.setPlanQty(10.0);
		for (SOperationTask opTask : partTask3.getOperationTaskList()) {
			opTask.setPlanQty(partTask3.getPlanQty());
		}

		LotAdvisor lotAdvisorImply = new LotAdvisor();
		Calendar calendarStart = Calendar.getInstance();
		calendarStart.set(2014, 1, 10, 0, 0);
		calendarStart.getTime();
		Date startDate = calendarStart.getTime();
		try {
			lotAdvisorImply.calSplitLocal(startDate, demandList, partTaskList);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.print("000");
		System.exit(0);
	}

	public Map<SPartTask, List<SPartTask>> calSplitLocal(Date startDate,
			List<Demand> demandList, List<SPartTask> partTaskList) throws Exception {
		
		double totalWip=0.0;
		double totalDemand=0.0;
		for (Demand demand:demandList) {
			totalDemand=totalDemand+demand.getDueQty();
		}
		for(SPartTask partTask:partTaskList){
			totalWip=totalWip+partTask.getPlanQty();
		}
		if(totalDemand<totalWip){
			throw new Exception("在制品数量不够，请投产");
		}
		
		double slack = 1.0;
		Collections.sort(partTaskList, new Comparator<Object>() {
			public int compare(Object o1, Object o2) {
				SPartTask partTask1 = (SPartTask) o1;
				SPartTask partTask2 = (SPartTask) o2;
				int i = 0;
				if (partTask1.getCurrentOperation().getOperationId() < partTask2
						.getCurrentOperation().getOperationId()) {
					i = 1;
				}
				return i;
			}
		});

		Collections.sort(demandList, new Comparator<Object>() {
			public int compare(Object o1, Object o2) {
				Demand demand1 = (Demand) o1;
				Demand demand2 = (Demand) o2;
				int i = 0;
				if (demand1.getLateFinish().after(demand2.getLateFinish())) {
					i = 1;
				}
				return i;
			}
		});

		List<TaskItemLocation> taskItemLocationList = new ArrayList<TaskItemLocation>();
		int totalLocation = 0;
		for (SPartTask partTask : partTaskList) {
			for (double i = 0; i < partTask.getPlanQty(); i++) {
				TaskItemLocation taskItemLocation = new TaskItemLocation();
				taskItemLocation.totalLocation = totalLocation;
				taskItemLocation.localLocation = (int) i;
				taskItemLocation.partTask = partTask;
				totalLocation = totalLocation + 1;
				taskItemLocationList.add(taskItemLocation);
			}
		}

		int demandStart = 0;
		int demandLoc = 0;

		double initNeed = demandList.get(0).getDueQty();
		int currTotalNeed = (int) initNeed;
		double sf1 = 999;
		for (int i = 0; i < taskItemLocationList.size(); i++) {
			if (demandLoc < demandList.size()) {
			Demand demand = demandList.get(demandLoc);
			taskItemLocationList.get(i).demand = demand;
			double planqty = demand.getDueQty();

			SPartTask bTask = taskItemLocationList.get(i).partTask;
			double bNum = bTask.getPlanQty();
			Date bbasedLateFinish = bTask.getLateFinish();

			double bqty = (double) (i - demandStart);
			Date blateFinish = demand.getLateFinish();
			updatePartTask(bTask, bqty, blateFinish);

			sf1 = calcSf(bTask, startDate);
			//demand.setBatchNum(sf1 + "");

			if ((i >= (currTotalNeed - 1)) && (sf1 < slack)) {


					demandLoc = demandLoc + 1;
					if(demandLoc<demandList.size()){
					demand = demandList.get(demandLoc);
					planqty = demand.getDueQty();
					currTotalNeed = currTotalNeed + (int) planqty;
					demandStart = i + 1;

					slack = slack * 1.2;
					}
			}
			updatePartTask(bTask, bNum, bbasedLateFinish);// 还原借算的零件任务

		}
		}
		// for (TaskItemLocation taskitem : taskItemLocationList) {
		// System.out.print(taskitem.demand.getNotes()
		// + taskitem.partTask.getNotes() + "松弛"
		// + taskitem.demand.getBatchNum());
		// System.out.print("___");
		// System.out.print("\n");
		// }

		for (Demand demand : demandList) {
			List<TaskItemLocation> demandPartTaskItemList = new ArrayList<TaskItemLocation>();
			for (TaskItemLocation taskItemLocation : taskItemLocationList) {
				if (demand.equals(taskItemLocation.demand)) {
					demandPartTaskItemList.add(taskItemLocation);
				}
			}

			//
			if (demandPartTaskItemList.size() > 0) {
				TaskItemLocation startItem = demandPartTaskItemList.get(0);
				double startPartDemandNeed = 0.0;
				for (int i = 0; i < demandPartTaskItemList.size(); i++) {
					if (demandPartTaskItemList.get(i).partTask
							.equals(startItem.partTask)) {
						startPartDemandNeed = startPartDemandNeed + 1;
					}
				}
				if (startPartDemandNeed < startItem.partTask.getPlanQty()) {
					SPartTask splitPartTask = new SPartTask();
					splitPartTask.setTaskUid(IdentityGenerator
							.GetIdentityString());
					splitPartTask.setPlanQty(startPartDemandNeed);
					splitPartTask.setLateFinish(demand.getLateFinish());
					splitPartTask.setNotes("需求" + demand.getNotes() + "分批");
					for (int i = 0; i < demandPartTaskItemList.size(); i++) {
						if (demandPartTaskItemList.get(i).partTask
								.equals(startItem.partTask)) {
							demandPartTaskItemList.get(i).splitTask = splitPartTask;
						}
					}
				}
				//
				TaskItemLocation endItem = demandPartTaskItemList
						.get(demandPartTaskItemList.size() - 1);
				double endPartDemandNeed = 0.0;
				for (int i = demandPartTaskItemList.size() - 1; i >= 0; i--) {
					if (demandPartTaskItemList.get(i).partTask
							.equals(endItem.partTask)) {
						endPartDemandNeed = endPartDemandNeed + 1;
					}
				}
				if (endPartDemandNeed < endItem.partTask.getPlanQty()) {
					SPartTask splitPartTask = new SPartTask();
					splitPartTask.setTaskUid(IdentityGenerator
							.GetIdentityString());
					splitPartTask.setPlanQty(endPartDemandNeed);
					splitPartTask.setLateFinish(demand.getLateFinish());
					splitPartTask.setNotes("需求" + demand.getNotes() + "分批");
					for (int i = demandPartTaskItemList.size() - 1; i >= 0; i--) {
						if (demandPartTaskItemList.get(i).partTask
								.equals(endItem.partTask)) {
							demandPartTaskItemList.get(i).splitTask = splitPartTask;
						}
					}
				}
			}
		}

		// for (TaskItemLocation taskitem : taskItemLocationList) {
		//
		// String split = "无";
		// if (taskitem.splitTask != null) {
		// split = taskitem.splitTask.getNotes();
		// }
		// System.out.print(taskitem.demand.getNotes()
		// + taskitem.partTask.getNotes() + "松弛"
		// + taskitem.demand.getBatchNum() + split);
		// System.out.print("___");
		// System.out.print("\n");
		// }

		Map<SPartTask, List<SPartTask>> splitSet = new HashMap<SPartTask, List<SPartTask>>();
		for (SPartTask partTask : partTaskList) {
			List<SPartTask> splitSpartTaskSet = new ArrayList<SPartTask>();
			splitSet.put(partTask, splitSpartTaskSet);
		}
		for (TaskItemLocation taskitem : taskItemLocationList) {
			if (splitSet.get(taskitem.partTask).contains(taskitem.splitTask)) {

			} else {
				splitSet.get(taskitem.partTask).add(taskitem.splitTask);
			}

		}
		//下面这一段主要是为了保证分批的数量一致
		for (SPartTask partTask:splitSet.keySet()) {
			List<SPartTask>splitList=splitSet.get(partTask);
			if(splitList!=null){
				if(splitList.size()>0){
					double oldQty=	partTask.getPlanQty();
					double newQty=0.0;
					for (SPartTask spliTask:splitList) {
						if(spliTask!=null){
						newQty=newQty+spliTask.getPlanQty();
						}
					}
					if(newQty<oldQty){
						SPartTask splitPartTask = new SPartTask();
						splitPartTask.setTaskUid(IdentityGenerator
								.GetIdentityString());
						splitPartTask.setPlanQty(oldQty-newQty);
						splitPartTask.setLateFinish(partTask.getScheme().getScheduleFinish());
						splitPartTask.setNotes("多余库存");
						splitList.add(splitPartTask);
					}
					}
					
			}
		}
		
		
		
		
		return splitSet;
	}

	public double calcSf(SPartTask partTask, Date startDate) {
		Date endDate = partTask.getLateFinish();
		int startday = (int) Math.round((startDate.getTime()) / (60000 * 1440));
		int endday = (int) Math.round((endDate.getTime()) / (60000 * 1440));
		int remainDay = endday - startday;
		int remain = remainDay * 15 * 60;

		double need = 0.0;
		for (SOperationTask optask : partTask.getOperationTaskList()) {
			need = need
					+ (optask.getPlanQty() * optask.getEstiRunTime() + optask
							.getEstiPreTime());
		}

		double slack = 999.0;
		if (need > 0) {
			slack = remain / need;
		}
		return slack;
	}

	public void updatePartTask(SPartTask partTask, double planQty,
			Date lateFinish) {
		List<SOperationTask> opList = partTask.getOperationTaskList();
		partTask.setLateFinish(lateFinish);
		for (SOperationTask opTask : opList) {
			opTask.setPlanQty(planQty);
			opTask.calTaskWork();
		}
	}

	 
	public Map<SPartTask, List<SPartTask>> calSplitAdvisor(Part part,
			List<Demand> demandList, List<SPartTask> schedulePartTaskList) throws Exception{
		// TODO Auto-generated method stub
		Date startDate = schedulePartTaskList.get(0).getScheme()
				.getScheduleStart();


			try {
				return calSplitLocal(startDate, demandList, schedulePartTaskList);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		return null;

	}
}
